The process of producing visual representations of geographic data, frequently on a map or in another geographical context, is referred to as geo-mapping. Depending on their geographic coordinates, points, lines, or areas can be displayed on a map.
Choropleth Maps display divided geographical areas or regions that are coloured, shaded or patterned in relation to a data variable. This provides a way to visualise values over a geographical area, which can show variation or patterns across the displayed location.
The data variable uses colour progression to represent itself in each region of the map. Typically, this can be a blending from one colour to another, a single hue progression, transparent to opaque, light to dark or an entire colour spectrum.
One downside to the use of colour is that you can't accurately read or compare values from the map.
Another issue is that larger regions appear more emphasised then smaller ones, so the viewer's perception of the shaded values are affected.
A common error when producing Choropleth Maps is to encode raw data values (such as population) rather than using normalized values (calculating population per square kilometre for example) to produce a density map.
Plotly is an open source library for Python. It integrates greatly with Jupyter Notebook and Dash to create interactive content for websites. It can be used to create ad hoc charts and professional content.
Handling spatial data for Geo Mapping needs some additional datasets and basic setup before you can use it for visual data representation and analysis.
E.g.Choropleth Charts are colored shapes and those shapes are of course manyfold. If you read through Plotly Documentation you can see that there are default shapes available in plotly for USA States and Countries as defined in the Natural Earth datasets.
To visualize data for Switzerland geo regions like cantons, districts or municipalities, we must explore other data sources for corresponding shapes to handle with.
Source/Links:
History:
Maps are not objective, but a version of reality. When creating them, lots of choices are made: What to map, how to map and whether or not to use a map in the first place?
Choropleth maps are great to show a clear regional pattern in the data, or for local data. Regional patterns could be an unusually high unemployment rate in neighboring counties or the contrast between cities and rural areas. If your data doesn’t show a clear regional pattern, consider another chart type for your data.
Choropleth maps work best when showing just one variable. This variable could be the difference between two variables (e.g. the change of the unemployment rate from last year to this year). But if you want to show the correlation between values, choropleth maps might be not your best choice. Consider a dot plot or scatterplot instead.
Choropleth maps are great to see the big picture, but not for subtle differences. Readers will have a hard time perceiving the small differences between colors on your map. In addition, the intervals between the colors are not necessarily the same intervals between the values in your data. That makes it easier to recognize patterns in the map, but makes it harder to compare the exact values of regions with each other. If you want to point out the numeric differences between regions, consider another chart type, a table or text instead. That also applies if your most important regions are too small to be shown on a map.
Choropleth maps work best for relative data. It would not be useful to map the absolute number of unemployed people in each county since we can’t compare that data without knowing the counties’ population. The unemployment rate (the number of unemployed people per 100 citizens) is more comparable. If you want to map absolute data, consider a symbol map instead. Be aware though, that this will often just answer the question “Where do most people live?”.
Consider cartograms if it’s important how many people are affected. Choropleth maps show us how much geographic area is affected. On some maps, this means that large regions where only a few people take up a lot of space on the screen. Population cartograms, on the other hand, drive more attention to populated areas. In countries with a very different population density in each state, cartograms can offer a more honest view of the data. However, be aware that cartograms make it harder for readers to recognize regions, so they work best if readers are familiar with the geography.
Consider choosing the smallest units possible. If you can use counties instead of states or NUTS2 regions instead of European countries, consider doing so. It will give readers a more refined image of the data and will let them spot more regional patterns. There are exceptions: For example, a state map is more informative in the winner-takes-it-all-system in the US presidential elections.
Make sure to use the right color scheme for your data. There are three different kinds of color schemes for maps:
Sequential (e.g. from bright blue to dark blue),
diverging (e.g. from red via white to blue),
and qualitative/categorical (e.g. one green color, one blue color).
Consider a sequential color scheme if you want to drive attention to the high values, e.g. for unemployment rates. Consider a diverging scheme if you want to drive the attention to both extremes of the scale, e.g. too show the difference in votes between two competing parties. With any color scheme, do use colorblind-friendly colors.
Consider using as few as possible colors in your qualitative color schemes. The more colors you use in your map, the harder it becomes for your readers to remember what they mean. Using only three colors means that your reader won’t need to check your color key too often. The colors shouldn’t give the idea of a sequential or diverging color scheme, if your data isn’t ordered in any way. You can use more than three colors if the reader already knows your color encoding, e.g. with colors of political parties.
Spend time thinking about your color key. Color keys are crucial for readers to understand your map. Make sure that they are quickly decipherable: Keys for sequential color schemes should show the colors for the lowest and highest values; plus two to four colors in between.
Consider using tooltips and labels. Tooltips are a great option to communicate the name and the underlying value of each region, since they will be hard to read otherwise. Tooltips also work well to communicate extra information about regions and remind reader’s what they’re seeing. Labels get more important the less your readers will know about the area you’re mapping.
The goal of GeoPandas is to make working with geospatial data in python easier. It combines the capabilities of pandas and shapely, providing geospatial operations in pandas and a high-level interface to multiple geometries to shapely. GeoPandas enables you to easily do operations in python that would otherwise require a spatial database such as PostGIS.
GeoPandas, as the name suggests, extends the popular data science library pandas by adding support for geospatial data.
The core data structure in GeoPandas is the
geopandas.GeoDataFrame, a subclass of
pandas.DataFrame, that can store geometry columns and perform spatial
operations.
The geopandas.GeoSeries, a subclass of
pandas.Series, handles the geometries.
Therefore, your GeoDataFrame is a combination of
pandas.Series, with traditional data (numerical, boolean,
text etc.), and geopandas.GeoSeries, with geometries
(points, polygons etc.).
You can have as many columns with geometries as you wish; there’s no limit typical for desktop GIS software.
!pip install pandas_geojsonCollecting pandas_geojson
Downloading pandas_geojson-2.0.0-py3-none-any.whl (12 kB)
Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (from pandas_geojson) (1.5.3)
Requirement already satisfied: python-dateutil>=2.8.1 in /usr/local/lib/python3.10/dist-packages (from pandas->pandas_geojson) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas->pandas_geojson) (2023.4)
Requirement already satisfied: numpy>=1.21.0 in /usr/local/lib/python3.10/dist-packages (from pandas->pandas_geojson) (1.25.2)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.1->pandas->pandas_geojson) (1.16.0)
Installing collected packages: pandas_geojson
Successfully installed pandas_geojson-2.0.0
# Load GEOPANDAS library
import geopandas as gpd# read Swiss Cantons Data + Geometry
geojson_file = 'https://raw.githubusercontent.com/sawubona-repo/BINA-FS24-WORK/master/zDiversExamples/Notebook-GeoMapping/DATA/ch-cantons.geojson'
# Read GeoJSON file into GeoDataFrame
geodf = gpd.read_file(geojson_file)
geodf.head()WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
| UUID | DATUM_AEND | DATUM_ERST | ERSTELL_J | ERSTELL_M | REVISION_J | REVISION_M | GRUND_AEND | HERKUNFT | HERKUNFT_J | ... | OBJEKTART | REVISION_Q | ICC | KANTONSNUM | SEE_FLAECH | KANTONSFLA | KT_TEIL | NAME | EINWOHNERZ | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | {0B2364ED-49E0-4D53-A33C-C684DD530B57} | 20181122133804 | 20121026122131 | 2012 | 10 | 2020 | 1 | Verbessert | AV | 2019 | ... | Kanton | 2019_Aufbau | CH | 18 | NaN | 710530.0 | 0 | Graubünden | 198379.0 | POLYGON ((8.87705 46.81291, 8.87783 46.81308, ... |
| 1 | {DDD56CEF-0E61-4EED-85ED-F67A459C93ED} | 20191106075758 | 20121026122131 | 2012 | 10 | 2020 | 1 | Verbessert | swisstopo | 2019 | ... | Kanton | 2019_Aufbau | CH | 2 | 11897.0 | 595951.0 | 1 | Bern | 1034977.0 | POLYGON ((8.04694 46.78711, 8.05029 46.78834, ... |
| 2 | {54B25E50-30A7-4995-ADE3-5FFF6E13A995} | 20181122133804 | 20121026122131 | 2012 | 10 | 2020 | 1 | Verbessert | AV | 2019 | ... | Kanton | 2019_Aufbau | CH | 23 | 1060.0 | 522463.0 | 0 | Valais | 343955.0 | POLYGON ((8.38472 46.45216, 8.38364 46.45151, ... |
| 3 | {921DFEF2-6D91-4CB8-9CFC-2A831C412020} | 20191106075758 | 20121026122131 | 2012 | 10 | 2020 | 1 | Verbessert | swisstopo | 2019 | ... | Kanton | 2019_Aufbau | CH | 22 | 39097.0 | 321202.0 | 1 | Vaud | 799145.0 | POLYGON ((7.07124 46.20101, 7.06621 46.19987, ... |
| 4 | {95F10F52-8B2F-4D6A-AF7E-D4F915E42F89} | 20181122133804 | 20121026122131 | 2012 | 10 | 2020 | 1 | Verbessert | AV | 2019 | ... | Kanton | 2019_Aufbau | CH | 21 | 7147.0 | 281216.0 | 0 | Ticino | 353343.0 | POLYGON ((8.38472 46.45216, 8.38474 46.45231, ... |
5 rows × 21 columns
geodf.info()# Load PLOTLY library
import plotly.express as px# List of diverging color scales for choropleth maps
fig = px.colors.diverging.swatches_continuous()
fig.show()Use population ("EINWOHNERZ") feature of the dataset
# Create Choropleth GeoMap with Population Data (Feature "EINWOHNERZ")
fig = px.choropleth_mapbox(
geodf,
geojson=geodf.geometry,
locations=geodf.index,
color='EINWOHNERZ', # define feature variable
color_continuous_scale=px.colors.diverging.Geyser, # built in color scale
labels={'EINWOHNERZ':'Einwohnerzahl 2020'},
hover_name='NAME',
hover_data={'KANTONSNUM':True, 'NAME':True, 'EINWOHNERZ':True},
opacity=0.5,
center=dict(lat=46.94809, lon=7.44744), # capital Bern as map center
zoom=6.5,
mapbox_style="carto-positron" # options "open-street-map"
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
fig.show()Use area ("KANTONSFLA") feature of the dataset
# Create Choropleth GeoMap with Area Data (Feature "KANTOSNFLA")
fig = px.choropleth_mapbox(
geodf,
geojson=geodf.geometry,
locations=geodf.index,
color='KANTONSFLA', # define feature variable
color_continuous_scale=px.colors.diverging.delta, # built in color scale
labels={'KANTONSFLA':'Kantonsfläche 2020'},
hover_name='NAME',
hover_data={'KANTONSNUM':True, 'NAME':True, 'KANTONSFLA':True},
opacity=0.5,
center=dict(lat=46.94809, lon=7.44744), # capital Bern as map center
zoom=6.5,
mapbox_style="carto-positron" # options "open-street-map"
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
fig.show()geodf GeoFrame# Load GEOPANDAS library
import geopandas as gpd# read Swiss Cantons Data + Geometry
geojson_file = 'https://raw.githubusercontent.com/sawubona-repo/BINA-FS24-WORK/master/zDiversExamples/Notebook-GeoMapping/DATA/ch-cantons.geojson'
# Read GeoJSON file into GeoDataFrame
raw_geodf = gpd.read_file(geojson_file)
raw_geodf.info()WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
WARNING:fiona.ogrext:Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
<class 'geopandas.geodataframe.GeoDataFrame'>
RangeIndex: 51 entries, 0 to 50
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 UUID 51 non-null object
1 DATUM_AEND 51 non-null object
2 DATUM_ERST 51 non-null object
3 ERSTELL_J 51 non-null int64
4 ERSTELL_M 51 non-null object
5 REVISION_J 51 non-null int64
6 REVISION_M 51 non-null object
7 GRUND_AEND 51 non-null object
8 HERKUNFT 51 non-null object
9 HERKUNFT_J 51 non-null int64
10 HERKUNFT_M 51 non-null object
11 OBJEKTART 51 non-null object
12 REVISION_Q 51 non-null object
13 ICC 51 non-null object
14 KANTONSNUM 51 non-null int64
15 SEE_FLAECH 19 non-null float64
16 KANTONSFLA 26 non-null float64
17 KT_TEIL 51 non-null object
18 NAME 51 non-null object
19 EINWOHNERZ 26 non-null float64
20 geometry 51 non-null geometry
dtypes: float64(3), geometry(1), int64(4), object(13)
memory usage: 8.5+ KB
# reduce the GeoFrame to necessary features/columns
geodf = raw_geodf
geodf.drop(["UUID", "DATUM_AEND","DATUM_ERST","ERSTELL_J","ERSTELL_M", "REVISION_J", "REVISION_M", "GRUND_AEND", "HERKUNFT", "HERKUNFT_J", "HERKUNFT_M", "OBJEKTART", "REVISION_Q", "ICC"], axis=1, inplace=True)
geodf.head(3)| KANTONSNUM | SEE_FLAECH | KANTONSFLA | KT_TEIL | NAME | EINWOHNERZ | geometry | |
|---|---|---|---|---|---|---|---|
| 0 | 18 | NaN | 710530.0 | 0 | Graubünden | 198379.0 | POLYGON ((8.87705 46.81291, 8.87783 46.81308, ... |
| 1 | 2 | 11897.0 | 595951.0 | 1 | Bern | 1034977.0 | POLYGON ((8.04694 46.78711, 8.05029 46.78834, ... |
| 2 | 23 | 1060.0 | 522463.0 | 0 | Valais | 343955.0 | POLYGON ((8.38472 46.45216, 8.38364 46.45151, ... |
# Rename and homogenize feature/column names in the Geoframe
geodf.rename(columns = {'KANTONSNUM':'KantonNr', 'NAME':'Kanton', 'SEE_FLAECH':'Fläche_See','KANTONSFLA':'Fläche_Kanton','EINWOHNERZ':'Anzahl_Einwohner_2020'}, inplace = True)
geodf.info()# Fill NA values and convert feature values to integers
geodf['Anzahl_Einwohner_2020'] = geodf['Anzahl_Einwohner_2020'].fillna(0).astype(int)
geodf['Anzahl_Einwohner_2020'] = geodf['Anzahl_Einwohner_2020'].astype(int)
geodf.info()<class 'geopandas.geodataframe.GeoDataFrame'>
RangeIndex: 51 entries, 0 to 50
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 KantonNr 51 non-null int64
1 Fläche_See 19 non-null float64
2 Fläche_Kanton 26 non-null float64
3 KT_TEIL 51 non-null object
4 Kanton 51 non-null object
5 Anzahl_Einwohner_2020 51 non-null int64
6 geometry 51 non-null geometry
dtypes: float64(2), geometry(1), int64(2), object(2)
memory usage: 2.9+ KB
bfsdf
DataFramesee BFS for the original data source
import pandas as pd# read BFS Data "Ständige Wohnbevölkerung, Stand 2022"
raw_bfs_file = 'https://raw.githubusercontent.com/sawubona-repo/BINA-FS24-WORK/main/zDiversExamples/DATA/BFS/BFS-CH-Kantone-St%C3%A4ndige-Wohnbev%C3%B6lkerung-2022.csv'
# Read CSV file into DataFrame
raw_bfsdf = pd.read_csv(bfs_file, sep=';')
raw_bfsdf.head()| KantonNr | KantonKürzel | Kanton | Total | Alter-0–19 | Alter-20–64 | Alter-65-und-mehr | Mann | Frau | Schweizer | ... | Ledig | Verheiratet | Verwitwet | Geschieden | Unverheiratet | EingetragenePartnerschaft | AufgelöstePartnerschaft | StädtischerKernraum | EinflussgebietstädtischerKerne | GebieteausserhalbEinflussgebietstädtischerKerne | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 19 | AG | Aargau | 711232 | 144909 | 433224 | 133099 | 357753 | 353479 | 524909 | ... | 308288 | 310713 | 31059 | 60103 | 32 | 803 | 212 | 388542 | 222279 | 100411 |
| 1 | 16 | AI | Appenzell I. Rh. | 16416 | 3392 | 9674 | 3350 | 8408 | 8008 | 14510 | ... | 7420 | 7045 | 855 | 1083 | 1 | 9 | 3 | 0 | 0 | 16416 |
| 2 | 15 | AR | Appenzell A. Rh. | 55759 | 11365 | 32747 | 11647 | 28114 | 27645 | 46395 | ... | 24016 | 23935 | 2744 | 4983 | 1 | 66 | 14 | 15744 | 26922 | 13093 |
| 3 | 2 | BE | Bern | 1051437 | 200509 | 620777 | 230151 | 516805 | 534632 | 872661 | ... | 469022 | 431354 | 54214 | 94967 | 57 | 1389 | 416 | 551861 | 234361 | 265215 |
| 4 | 13 | BL | Basel-Landschaft | 294417 | 56709 | 170422 | 67286 | 144441 | 149976 | 223876 | ... | 121799 | 130051 | 15814 | 26126 | 13 | 504 | 104 | 199822 | 87691 | 6904 |
5 rows × 21 columns
raw_bfsdf.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 26 entries, 0 to 25
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 KantonNr 26 non-null int64
1 KantonKürzel 26 non-null object
2 Kanton 26 non-null object
3 Total 26 non-null int64
4 Alter-0–19 26 non-null int64
5 Alter-20–64 26 non-null int64
6 Alter-65-und-mehr 26 non-null int64
7 Mann 26 non-null int64
8 Frau 26 non-null int64
9 Schweizer 26 non-null int64
10 Ausländer 26 non-null int64
11 Ledig 26 non-null int64
12 Verheiratet 26 non-null int64
13 Verwitwet 26 non-null int64
14 Geschieden 26 non-null int64
15 Unverheiratet 26 non-null int64
16 EingetragenePartnerschaft 26 non-null int64
17 AufgelöstePartnerschaft 26 non-null int64
18 StädtischerKernraum 26 non-null int64
19 EinflussgebietstädtischerKerne 26 non-null int64
20 GebieteausserhalbEinflussgebietstädtischerKerne 26 non-null int64
dtypes: int64(19), object(2)
memory usage: 4.4+ KB
# Rename and homogenize feature/column names in the Dataframe
bfsdf = raw_bfsdf
bfsdf.rename(columns = {'Total':'Anzahl_Einwohner_2022'}, inplace = True)
bfsdf.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 26 entries, 0 to 25
Data columns (total 21 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 KantonNr 26 non-null int64
1 KantonKürzel 26 non-null object
2 Kanton 26 non-null object
3 Anzahl_Einwohner_2022 26 non-null int64
4 Alter-0–19 26 non-null int64
5 Alter-20–64 26 non-null int64
6 Alter-65-und-mehr 26 non-null int64
7 Mann 26 non-null int64
8 Frau 26 non-null int64
9 Schweizer 26 non-null int64
10 Ausländer 26 non-null int64
11 Ledig 26 non-null int64
12 Verheiratet 26 non-null int64
13 Verwitwet 26 non-null int64
14 Geschieden 26 non-null int64
15 Unverheiratet 26 non-null int64
16 EingetragenePartnerschaft 26 non-null int64
17 AufgelöstePartnerschaft 26 non-null int64
18 StädtischerKernraum 26 non-null int64
19 EinflussgebietstädtischerKerne 26 non-null int64
20 GebieteausserhalbEinflussgebietstädtischerKerne 26 non-null int64
dtypes: int64(19), object(2)
memory usage: 4.4+ KB
bfsdf_sel of the
entire bfsdf DataFrame# define selection
bfsdf_sel = bfsdf[['KantonNr', 'Kanton', 'Anzahl_Einwohner_2022', 'Mann', 'Frau', 'Geschieden', 'Schweizer', 'StädtischerKernraum']]bfsdf_sel.head()| KantonNr | Kanton | Anzahl_Einwohner_2022 | Mann | Frau | Geschieden | Schweizer | StädtischerKernraum | |
|---|---|---|---|---|---|---|---|---|
| 0 | 19 | Aargau | 711232 | 357753 | 353479 | 60103 | 524909 | 388542 |
| 1 | 16 | Appenzell I. Rh. | 16416 | 8408 | 8008 | 1083 | 14510 | 0 |
| 2 | 15 | Appenzell A. Rh. | 55759 | 28114 | 27645 | 4983 | 46395 | 15744 |
| 3 | 2 | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 |
| 4 | 13 | Basel-Landschaft | 294417 | 144441 | 149976 | 26126 | 223876 | 199822 |
# Add additional features, proportional values etc.
# Calculate the fraction of "Schweizer" on the "Anzahl_Einwohner_2022"
bfsdf_sel["zAnteil_Schweizer"] = bfsdf_sel.apply(lambda row: row['Schweizer'] / row['Anzahl_Einwohner_2022'], axis=1)
# Calculate the ratio of "Mann" versus "Frau"
bfsdf_sel["zRatio_MannFrau"] = bfsdf_sel.apply(lambda row: row['Mann'] / row['Frau'], axis=1)
# Calculate the fraction of "Schweizer" on the "Anzahl_Einwohner_2022"
bfsdf_sel["zAnteil_Geschieden"] = bfsdf_sel.apply(lambda row: row['Geschieden'] / row['Anzahl_Einwohner_2022'], axis=1)
# Calculate the ratio of "StädtischerKernraum" versus "Anzahl_Einwohner_2022"
bfsdf_sel["zRatio_Städtisch"] = bfsdf_sel.apply(lambda row: row['StädtischerKernraum'] / row['Anzahl_Einwohner_2022'], axis=1)<ipython-input-71-dfd37ee35fc7>:4: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
<ipython-input-71-dfd37ee35fc7>:7: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
<ipython-input-71-dfd37ee35fc7>:10: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
<ipython-input-71-dfd37ee35fc7>:13: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
bfsdf_sel.head()| KantonNr | Kanton | Anzahl_Einwohner_2022 | Mann | Frau | Geschieden | Schweizer | StädtischerKernraum | zAnteil_Schweizer | zRatio_MannFrau | zAnteil_Geschieden | zRatio_Städtisch | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 19 | Aargau | 711232 | 357753 | 353479 | 60103 | 524909 | 388542 | 0.738028 | 1.012091 | 0.084505 | 0.546294 |
| 1 | 16 | Appenzell I. Rh. | 16416 | 8408 | 8008 | 1083 | 14510 | 0 | 0.883894 | 1.049950 | 0.065972 | 0.000000 |
| 2 | 15 | Appenzell A. Rh. | 55759 | 28114 | 27645 | 4983 | 46395 | 15744 | 0.832063 | 1.016965 | 0.089367 | 0.282358 |
| 3 | 2 | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 | 0.829970 | 0.966656 | 0.090321 | 0.524864 |
| 4 | 13 | Basel-Landschaft | 294417 | 144441 | 149976 | 26126 | 223876 | 199822 | 0.760404 | 0.963094 | 0.088738 | 0.678704 |
#merge GeoFrame with DataFrame on corresponding "KantonNr" column values
joined_geodf = pd.merge(geodf, bfsdf_sel, on=["KantonNr"])
joined_geodf.shape
joined_geodf.info()<class 'geopandas.geodataframe.GeoDataFrame'>
Int64Index: 51 entries, 0 to 50
Data columns (total 18 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 KantonNr 51 non-null int64
1 Fläche_See 19 non-null float64
2 Fläche_Kanton 26 non-null float64
3 KT_TEIL 51 non-null object
4 Kanton_x 51 non-null object
5 Anzahl_Einwohner_2020 51 non-null int64
6 geometry 51 non-null geometry
7 Kanton_y 51 non-null object
8 Anzahl_Einwohner_2022 51 non-null int64
9 Mann 51 non-null int64
10 Frau 51 non-null int64
11 Geschieden 51 non-null int64
12 Schweizer 51 non-null int64
13 StädtischerKernraum 51 non-null int64
14 zAnteil_Schweizer 51 non-null float64
15 zRatio_MannFrau 51 non-null float64
16 zAnteil_Geschieden 51 non-null float64
17 zRatio_Städtisch 51 non-null float64
dtypes: float64(6), geometry(1), int64(8), object(3)
memory usage: 7.6+ KB
joined_geodf.head()| KantonNr | Fläche_See | Fläche_Kanton | KT_TEIL | Kanton_x | Anzahl_Einwohner_2020 | geometry | Kanton_y | Anzahl_Einwohner_2022 | Mann | Frau | Geschieden | Schweizer | StädtischerKernraum | zAnteil_Schweizer | zRatio_MannFrau | zAnteil_Geschieden | zRatio_Städtisch | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 18 | NaN | 710530.0 | 0 | Graubünden | 198379 | POLYGON ((8.87705 46.81291, 8.87783 46.81308, ... | Graubünden | 202538 | 101760 | 100778 | 17628 | 162686 | 66483 | 0.803237 | 1.009744 | 0.087036 | 0.328250 |
| 1 | 2 | 11897.0 | 595951.0 | 1 | Bern | 1034977 | POLYGON ((8.04694 46.78711, 8.05029 46.78834, ... | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 | 0.829970 | 0.966656 | 0.090321 | 0.524864 |
| 2 | 2 | NaN | NaN | 2 | Bern | 0 | POLYGON ((7.55835 47.32237, 7.55716 47.32262, ... | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 | 0.829970 | 0.966656 | 0.090321 | 0.524864 |
| 3 | 2 | NaN | NaN | 3 | Bern | 0 | POLYGON ((7.12304 46.90020, 7.12136 46.90051, ... | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 | 0.829970 | 0.966656 | 0.090321 | 0.524864 |
| 4 | 2 | NaN | NaN | 4 | Bern | 0 | POLYGON ((7.09086 46.90382, 7.09089 46.90336, ... | Bern | 1051437 | 516805 | 534632 | 94967 | 872661 | 551861 | 0.829970 | 0.966656 | 0.090321 | 0.524864 |
geodf2 = joined_geodf# Load PLOTLY library
import plotly.express as px# Create Choropleth GeoMap with Population Data (Feature "zAnteil_Schweizer")
fig = px.choropleth_mapbox(
geodf2,
geojson=geodf2.geometry,
locations=geodf2.index,
color='zAnteil_Schweizer', # define feature variable
color_continuous_scale=px.colors.diverging.Geyser, # built in color scale
labels={'zAnteil_Schweizer':'Anteil Schweizer an der Gesamtbevölkerung 2022'},
hover_name='KantonNr',
hover_data={'KantonNr':True, 'Kanton_x':True, 'Anzahl_Einwohner_2022':True, 'zAnteil_Schweizer':True},
opacity=0.5,
center=dict(lat=46.94809, lon=7.44744), # capital Bern as map center
zoom=6.5,
mapbox_style="carto-positron" # options "open-street-map"
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
fig.show()# Create Choropleth GeoMap with Population Data (Feature "zRatio_MannFrau")
fig = px.choropleth_mapbox(
geodf2,
geojson=geodf2.geometry,
locations=geodf2.index,
color='zRatio_MannFrau', # define feature variable
color_continuous_scale=px.colors.diverging.RdBu, # built in color scale
labels={'zRatio_MannFrau':'Ratio Mann vs. Frau in der Gesamtbevölkerung 2022'},
hover_name='KantonNr',
hover_data={'KantonNr':True, 'Kanton_x':True, 'Anzahl_Einwohner_2022':True, 'zRatio_MannFrau':True},
opacity=0.5,
center=dict(lat=46.94809, lon=7.44744), # capital Bern as map center
zoom=6.5,
mapbox_style="carto-positron" # options "open-street-map"
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
fig.show()# Create Choropleth GeoMap with Population Data (Feature "zRatio_Städtisch")
fig = px.choropleth_mapbox(
geodf2,
geojson=geodf2.geometry,
locations=geodf2.index,
color='zRatio_Städtisch', # define feature variable
color_continuous_scale=px.colors.diverging.PuOr, # built in color scale
labels={'zRatio_Städtisch':'Ratio städtische Population an der Gesamtbevölkerung 2022'},
hover_name='KantonNr',
hover_data={'KantonNr':True, 'Kanton_x':True, 'Anzahl_Einwohner_2022':True, 'zRatio_Städtisch':True},
opacity=0.5,
center=dict(lat=46.94809, lon=7.44744), # capital Bern as map center
zoom=6.5,
mapbox_style="carto-positron" # options "open-street-map"
)
fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))
fig.show()